#ifndef  HELPER_OBJECT_OBJECTFACTORY_H
#define  HELPER_OBJECT_OBJECTFACTORY_H

#include <memory>

#include "helper/object/RawType.h"
#include "helper/object/String.h"
#include "helper/object/Pointer.h"
#include "helper/object/Array.h"
#include "helper/object/Hash.h"

#include "helper/Singleton.h"

namespace helper {
namespace object {

class ObjectFactory {
public:
    ObjectFactory(){}
    virtual ~ObjectFactory(){}

    inline std::shared_ptr<String> createStupidString(){
        return std::shared_ptr<String>(createString());
    }
    inline std::shared_ptr<String> createStupidString(const std::string & str){
        return std::shared_ptr<String>(createString(str));
    }
    inline std::shared_ptr<Array> createStupidArray(){
        return std::shared_ptr<Array>(createArray());
    }
    inline std::shared_ptr<Hash> createStupidHash(){
        return std::shared_ptr<Hash>(createHash());
    }
    inline std::shared_ptr<Byte> createStupidByte(const char val){
        return std::shared_ptr<Byte>(createByte(val));
    }
    inline std::shared_ptr<Integer> createStupidInteger(const long long val){
        return std::shared_ptr<Integer>(createInteger(val));
    }
    inline std::shared_ptr<Double> createStupidDouble(const double val){
        return std::shared_ptr<Double>(createDouble(val));
    }

    virtual Byte * createByte(const char val) const = 0;
    virtual Integer * createInteger(const long long val) const = 0;
    virtual Double * createDouble(const double val) const = 0;

    virtual Pointer * createPointer(const void * val) const = 0;

    virtual String * createString(const std::string & str) const = 0;
    virtual String * createString(const char * str) const = 0;
    virtual String * createString(const char * buffer, size_t len) const = 0;
    virtual String * createString(const char * buffer, size_t offset, size_t len) const = 0;
    virtual String * createString(size_t n, const char ch) const = 0;
    virtual String * createString() const = 0;

    virtual Array * createArray() const = 0;
    virtual Hash * createHash() const = 0;

    virtual std::string toString() const = 0;

	static ObjectFactory * createDefault();
};



class DefaultObjectFactory : public helper::Singleton<DefaultObjectFactory> {
public:
    DefaultObjectFactory();
    ~DefaultObjectFactory() override;

    inline ObjectFactory & get(){
        return *factory;
    }
    inline const ObjectFactory * getPtr() const {
        return factory;
    }
    inline ObjectFactory * getPtr() {
        return factory;
    }
private:
    ObjectFactory  *  factory;
};

} // end of namespace object
} // end of namespace helper

#endif   /* HELPER_OBJECT_OBJECTFACTORY_H */
